#pragma once
#include <iostream>
#include <vector>
#include <unistd.h>
#include <string>
#include "task.hpp"
#include <sys/wait.h>
// 先描述
class Pipe
{
public:
    Pipe(int wfd, pid_t subid) : _wfd(wfd), _childid(subid)
    {
        _name = "child-" + std::to_string(_wfd) + "-" + std::to_string(_childid);
    }
    // 发送命令
    void send(int code)
    {
        write(_wfd, &code, sizeof(code));
    }
    // 写关读开，读会自动关闭
    void Close()
    {
        close(_wfd);
    }
    void waitchild()
    {
        waitpid(_childid, nullptr, 0);
    }
    int getwfd() { return _wfd; }
    pid_t getchildid() { return _childid; }
    std::string &getname() { return _name; }
    ~Pipe()
    {
    }

private:
    int _wfd;
    pid_t _childid;
    std::string _name;
};
// 组织
// 对管道进行管理
class PipeManage
{
public:
    PipeManage() : next(0)
    {
    }
    // 依次让管道进行工作
    Pipe &select()
    {
        int current = next;
        next = (next + 1) % _Pipe.size();
        return _Pipe[current];
    }
    void AddPipe(int wfd, pid_t subid)
    {
        _Pipe.emplace_back(wfd, subid);
    }
    void print()
    {
        for (auto &e : _Pipe)
        {
            std::cout << e.getname() << std::endl;
        }
    }
    void Close()
    {
        for (auto &e : _Pipe)
        {
            e.Close();
            std::cout << "关闭了写文件：" << e.getwfd() << std::endl;
        }
    }
    void Wait()
    {
        for (auto &e : _Pipe)
        {
            e.waitchild();
            std::cout << "关闭了进程：" << e.getname() << std::endl;
        }
    }
    ~PipeManage()
    {
    }

private:
    // 使用vector管理管道
    std::vector<Pipe> _Pipe;
    int next;
};

const int pross_num = 5;

class ProcessPool
{
public:
    ProcessPool(int num) : ProcessNum(num)
    {
        tk.AddFun(PrintLog);
        tk.AddFun(Download);
        tk.AddFun(Upload);
    }
    void Work(int rfd)
    {

        while (true)
        {
            int code = 0;
            ssize_t count = read(rfd, &code, sizeof(code));
            if (count > 0)
            {
                std::cout << "子进程：" << getpid() << "收到任务码：" << code << std::endl;
                tk.Execute(code); // 执行任务
                // sleep(1);
            }
            else if (count == 0)
            {
                std::cout << "子进程退出" << std::endl;
                break;
            }
            else
            {
                std::cout << "读取失败" << std::endl;
                break;
            }
        }
    }
    bool start()
    {
        for (int i = 0; i < ProcessNum; i++)
        {
            int fd[2];
            if (pipe(fd) == -1)
            {
                std::cerr << "fd\n"
                          << std::endl;
                return false;
            }
            pid_t subid = fork();
            if (subid < 0)
            {
                return false;
            }
            else if (subid == 0)
            {
                // child
                close(fd[1]); // 关闭写
                //_Pm.Close();
                Work(fd[0]);
                close(fd[0]);
                exit(0);
            }
            else
            {
                // father
                close(fd[0]);
                _Pm.AddPipe(fd[1], subid); // 将父亲的写文件描述符与子进程的pid传入
            }
        }
        return true;
    }
    void run()
    {
        int taskcode = tk.code(); // 选择一个任务
        auto Pp = _Pm.select();   // 选择一个管道
        std::cout << "选择了一个进程" << Pp.getname() << std::endl;
        // 发送任务
        Pp.send(taskcode);
        std::cout << "任务码为：" << taskcode << std::endl;
    }
    void debug()
    {
        _Pm.print();
    }
    void StopProcess()
    {
        _Pm.Close();
        _Pm.Wait();
    }
    ~ProcessPool()
    {
    }

private:
    PipeManage _Pm;
    int ProcessNum;
    task tk;
};